use crate::types::{PoolInfo, TokenValidation};
use anyhow::Result;
use solana_client::rpc_client::RpcClient;
use solana_sdk::pubkey::Pubkey;
use spl_token::state::Mint;
use solana_program::program_pack::Pack;

pub struct TokenValidator {
    rpc_client: RpcClient,
}

impl TokenValidator {
    pub fn new(rpc_url: String) -> Self {
        Self {
            rpc_client: RpcClient::new(rpc_url),
        }
    }

    pub async fn validate_token(&self, pool_info: &PoolInfo) -> Result<TokenValidation> {
        let mint_renounced = self.check_if_mint_is_renounced(&pool_info.mint_a).await?;
        let not_freezable = self.check_if_not_freezable(&pool_info.mint_a).await?;
        let liquidity_valid = self.check_liquidity_range(pool_info);

        Ok(TokenValidation {
            is_mint_renounced: mint_renounced,
            is_not_freezable: not_freezable,
            liquidity_in_range: liquidity_valid,
        })
    }

    async fn check_if_mint_is_renounced(&self, mint: &Pubkey) -> Result<bool> {
        let account_info = self.rpc_client.get_account(mint)?;
        let mint_data = Mint::unpack(&account_info.data)?;
        
        // 检查mint authority是否为None（已放弃所有权）
        Ok(mint_data.mint_authority.is_none())
    }

    async fn check_if_not_freezable(&self, mint: &Pubkey) -> Result<bool> {
        let account_info = self.rpc_client.get_account(mint)?;
        let mint_data = Mint::unpack(&account_info.data)?;
        
        // 检查freeze authority是否为None（不可冻结）
        Ok(mint_data.freeze_authority.is_none())
    }

    fn check_liquidity_range(&self, pool_info: &PoolInfo) -> bool {
        // 检查流动性是否在138-150.423 SOL范围内
        let total_liquidity = pool_info.liquidity_sol + pool_info.liquidity_wsol;
        total_liquidity > 138.0 && total_liquidity < 150.423
    }
}

pub fn parse_pool_from_account_data(account_data: &[u8], pubkey: &Pubkey) -> Result<PoolInfo> {
    // 验证数据长度
    if account_data.len() < 8 {
        return Err(anyhow::anyhow!("账户数据长度不足"));
    }
    
    // 跳过账户标识符（8字节）
    let data = &account_data[8..];
    
    // 验证数据长度
    if data.len() < 128 {
        return Err(anyhow::anyhow!("池子数据长度不足"));
    }
    
    // 解析代币铸币地址
    let mint_a = Pubkey::new_from_array(data[0..32].try_into()?);
    let mint_b = Pubkey::new_from_array(data[32..64].try_into()?);
    
    // 解析流动性数据
    // 注意：这里使用更准确的数据布局
    let liquidity_sol = u64::from_le_bytes(data[64..72].try_into()?) as f64 / 1e9;
    let liquidity_wsol = u64::from_le_bytes(data[72..80].try_into()?) as f64 / 1e9;
    
    // 验证数据有效性
    if liquidity_sol <= 0.0 || liquidity_wsol <= 0.0 {
        return Err(anyhow::anyhow!("无效的流动性数据"));
    }
    
    Ok(PoolInfo {
        id: *pubkey,
        mint_a,
        mint_b,
        liquidity_sol,
        liquidity_wsol,
    })
}

// 改进重试机制
pub async fn retry_operation<F, Fut, T, E>(operation: F, max_retries: u32, delay_ms: u64) -> Result<T>
where
    F: Fn() -> Fut,
    Fut: std::future::Future<Output = Result<T, E>>,
    E: std::fmt::Display,
{
    let mut retries = 0;
    loop {
        match operation().await {
            Ok(result) => return Ok(result),
            Err(e) => {
                if retries >= max_retries {
                    return Err(anyhow::anyhow!("操作失败，已达到最大重试次数: {}", e));
                }
                retries += 1;
                log::warn!("操作失败，正在进行第 {} 次重试: {}", retries, e);
                tokio::time::sleep(tokio::time::Duration::from_millis(delay_ms)).await;
            }
        }
    }
} 